package edu.spsu.events;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TableRow.LayoutParams;
import android.widget.TextView;
import edu.spsu.R;
import edu.spsu.utils.Util;

public class EventListingActivity extends Activity {
	private static String TAG = EventListingActivity.class.getName();
	
	private class MyOnItemSelectedListener implements OnItemSelectedListener {
		public void onItemSelected(AdapterView<?> parent,View view, int pos, long id) {
			String feedString = readCalendarFeed(createFeedLinkWithEnding(FEED_ENDINGS[pos]));
			EventListingActivity.clearData(eventList);
			EventListingActivity.parseJsonData(feedString,eventList);
			loadDataIntoTable((TableLayout) findViewById(R.id.eventTableLayout),eventList);
			//Scroll up
			ScrollView scrollView = (ScrollView)findViewById(R.id.scrollView);
			scrollView.scrollTo(0, 0);
		}		
		public void onNothingSelected(AdapterView parent) {
			//do nothing for now.
		}
	}
	
	private ArrayList<CalendarEvent> eventList;
	
	//Beginning of Calendar Feed For ALL feeds
	private static final String CALENDAR_LINK_START = "http://calendar.spsu.edu/webcache/v1.0/jsonDays/";
	//Default days to look up for initial feed lookup 
	private static final String DEFAULT_DAYS = "2";
	
	//Ending of all the feeds to append
	private static final String ACADEMIC_CALENDAR_FEED_ENDING = "/list-json/%28catuid%3D%27ff808181-1fd7389e-011f-d7389f4b-00000018%27%29/no--object.json";
	private static final String ARTS_FEED_ENDING = "/list-json/%28catuid%3D%27ff808181-1fd73b03-011f-d73b0642-00000001%27%29/no--object.json";
	private static final String ATHLETICS_FEED_ENDING = "/list-json/%28catuid%3D%27ff808181-1fd7389e-011f-d7389f24-0000000e%27%29/no--object.json";
	private static final String CLUBS_FEED_ENDING = "/list-json/%28catuid%3D%27402881e6-20a21413-0120-a23d71e5-00000015%27%29/no--object.json";
	private static final String CONFERENCES_FEED_ENDING = "/list-json/%28catuid%3D%27ff808181-1fd73b03-011f-d73b066b-00000004%27%29/no--object.json";
	private static final String LECTURES_FEED_ENDING = "/list-json/%28catuid%3D%27ff808181-1fd73b03-011f-d73b06e0-0000000a%27%29/no--object.json";
	private static final String OTHER_EVENTS_FEED_ENDING = "/list-json/%28catuid%3D%27ff808181-1fd73b03-011f-d73b06f2-0000000b%27%29/no--object.json";
	private static final String SOCIAL_EVENTS_FEED_ENDING = "/list-json/%28catuid%3D%27ff808181-1fd73b03-011f-d73b0703-0000000d%27%29/no--object.json";
	private static final String SPECIAL_EVENTS_FEED_ENDING = "/list-json/%28catuid%3D%27ff808181-1fd7389e-011f-d7389f20-0000000d%27%29/no--object.json";
	private static final String TRAINING_FEED_ENDING = "/list-json/%28catuid%3D%27ff808181-1fd7389e-011f-d7389f2c-00000010%27%29/no--object.json";	
	
	private static final String[] FEED_ENDINGS = {
		ACADEMIC_CALENDAR_FEED_ENDING,
		ARTS_FEED_ENDING,
		ATHLETICS_FEED_ENDING,
		CLUBS_FEED_ENDING,
		CONFERENCES_FEED_ENDING,
		LECTURES_FEED_ENDING,
		OTHER_EVENTS_FEED_ENDING,
		SOCIAL_EVENTS_FEED_ENDING,
		SPECIAL_EVENTS_FEED_ENDING,
		TRAINING_FEED_ENDING };
	
	//Padding for the table cells
	public static final int TABLE_CELL_PADDING = 3;
	//List Separator Color
	public static final int SEPARATOR_COLOR=Color.DKGRAY;
	//List Separator Size in pixels
	public static final int SEPARATOR_SIZE=2;
    
    /**
     * Converts a String from SPSU's JSON Feeds into a java Date
     * @param dateString The String from spsu.edu to convert into a java Date
     * @return The converted Date
     */
    public Date convertToDate(String dateString) {
    	Date date = null;
    	SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yy");
    	try {
    		date = formatter.parse(dateString);
    	} 
    	catch(Exception e) {
    		Log.e(TAG,"Parsing Exception="+e);
    	}
    	return date;
    }
    
    /**
     * Reloads our tablelayout
     * @param eventTableLayout The TableLayout to reload
     * @param eventList The ArrayList to fill the table layout with
     */
    public void loadDataIntoTable(TableLayout eventTableLayout, ArrayList<CalendarEvent> eventList) {
        //Loop through and create table rows
        eventTableLayout.removeAllViews();
    	for(int i=0;i<eventList.size();++i) {
        	//Add rows for this event to the table
        	addSeparator(eventTableLayout);
        	addTableRowToTable("Title:",eventList.get(i).title, i, eventTableLayout);
        	addTableRowToTable("Description:",eventList.get(i).description, i, eventTableLayout);  
        	String startDate = eventList.get(i).startDate;
        	String startTime = eventList.get(i).startTime;
        	if(startOfDay(new Date()).equals(convertToDate(startDate))) { //Started Today. 
            	addTableRowToTable("Starts:","Today @ "+eventList.get(i).startTime, i, eventTableLayout);        		
        	} else { // Didn't start today
        		if(startOfDay(new Date()).compareTo(convertToDate(startDate))<0) { //now's date is before the starting date
        			addTableRowToTable("Starts:",startDate+" @ "+startTime, i, eventTableLayout);
        		} else { //now's date is after the starting date
        			addTableRowToTable("Started:",startDate+" @ "+startTime, i, eventTableLayout);
        		}
        	}        	
        	String endDate = eventList.get(i).endDate;
        	String endTime = eventList.get(i).endTime;
        	if(startOfDay(new Date()).equals(convertToDate(endDate))) { //Ended Today. 
            	addTableRowToTable("Ends:","Today @ "+endTime, i, eventTableLayout);        		
        	} else { // Didn't start today
        		if(startOfDay(new Date()).compareTo(convertToDate(endDate))<0) { //now's date is before the ending date
        			addTableRowToTable("Ends:",endDate+" @ "+endTime, i, eventTableLayout);
        		} else { //now's date is after the ending date
        			addTableRowToTable("Ended:",endDate+" @ "+endTime, i, eventTableLayout);
        		}
        	}
        	addTableRowToTable("Contact:",eventList.get(i).contactName, i, eventTableLayout);
        	addTableRowToTable("Phone #:",eventList.get(i).contactNumber, i, eventTableLayout);
        	addSeparator(eventTableLayout);
        }
    }
    
    /** 
     * Takes in a Date and returns the beginning of that Date
     * Found this on stackoverflow.com somewhere.  I can't find it again for the life of me. 
     * <link here>
     * @param date The date to change
     * @return The beginning of the date passed in
     */
    public static Date startOfDay(Date date) {
    	   Calendar dCal = Calendar.getInstance();
    	   dCal.setTime(date);
    	   dCal.set(Calendar.HOUR_OF_DAY, 0);
    	   dCal.set(Calendar.MINUTE, 0);
    	   dCal.set(Calendar.SECOND, 0);
    	   dCal.set(Calendar.MILLISECOND, 0);
    	   return dCal.getTime();
    	 }
    
    /**
     * Clears the data from the Arraylist passed in
     * @param eventList The Arraylist to clear the data from
     */
    public static void clearData(ArrayList<CalendarEvent> eventList) {
    	eventList.clear();
    }
    
    /**
     * Pases JSON data into our ArrayList
     * @param feedString The String of JSON Data
     * @param eventList The Arraylist to add the JSON Data to upon conversion
     */
    public static void parseJsonData(String feedString, ArrayList<CalendarEvent> eventList) {
    	try { 
        	//JSON Parsing.
        	JSONObject jsonObjectFeed = new JSONObject(feedString);
        	JSONObject jsonEventsList = jsonObjectFeed.getJSONObject("bwEventList");
        	JSONArray jsonEventArray = jsonEventsList.getJSONArray("events");
        	for(int i = 0 ; i < jsonEventArray.length() ; i++){
        		String title="", startDate="", startTime="", endDate="", endTime="", description="", contactName="", contactNumber="", location="";
        		//Get this event
        	    JSONObject thisJsonEvent = jsonEventArray.getJSONObject(i);         	    
        	    //Grab nested objects
        	    JSONObject startObject = thisJsonEvent.getJSONObject("start");
        	    JSONObject endObject = thisJsonEvent.getJSONObject("end");
        	    JSONObject locationObject = thisJsonEvent.getJSONObject("location");
        	    JSONObject contactObject = thisJsonEvent.getJSONObject("contact");
        	    //Grab data
        	    title = sanitizeInput(thisJsonEvent.getString("summary"));
        	    startDate = startObject.getString("shortdate");
        	    startTime = startObject.getString("time");
        	    endDate = endObject.getString("shortdate");
        	    endTime = endObject.getString("time");
        	    description = sanitizeInput(thisJsonEvent.getString("description"));
        	    contactName = contactObject.getString("name");
        	    contactNumber = contactObject.getString("phone");
        	    location = locationObject.getString("address");
        	    //Make new event and add it to our arraylist
        	    CalendarEvent newEvent = new CalendarEvent(title,startDate,startTime,endDate,endTime,description,contactName,contactNumber,location);
        	    eventList.add(newEvent);
        	}
        } catch (Exception e) {
        	Log.e(TAG,"Exception="+e);
        } 
    }
    
    /**
     * Creates a Link from the end of the URL that was passed in 
     * (All the links have the same beginning)
     * @param ending The end of the URL
     * @return The completed URL
     */
    public String createFeedLinkWithEnding(String ending) {
   		int days = eventList.size();
   		days+=Integer.parseInt(DEFAULT_DAYS);
   		String toReturn = CALENDAR_LINK_START+Integer.toString(days)+ending;
   		return toReturn;
    }
    
    /**
     * I sanitize the JSON input (to convert &amp; into & for now)
     * @param input The input to sanitize
     * @return The sanitized ready to display input
     */
    public static String sanitizeInput(String input) {
    	return input.replace("&amp;","&");
    }
    
    /**
     * I add a separator the the TableLayout that is passed in
     * @param eventTableLayout The TableLayout to add the separator to
     */
    public void addSeparator(TableLayout eventTableLayout) {
    	TextView listSeparator = new TextView(this);
    	listSeparator.setTextSize(SEPARATOR_SIZE);
    	listSeparator.setBackgroundColor(SEPARATOR_COLOR);
    	eventTableLayout.addView(listSeparator);
    }   
    
    /**
     * Adds a row to the table layout passed in
     * @param title The title of this row
     * @param text The text to use in column 1
     * @param i The index of this item
     * @param tableLayout The table layout to add the row to
     */
    public void addTableRowToTable(String title, String text, int i, TableLayout tableLayout) {
    	if(text.equals("") || text==null) { //Null or empty String passed.  Add nothing.
    		return;
    	}
    	TableRow tableRow = new TableRow(this);
    	tableRow.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
    	TextView textView = new TextView(this);
    	textView.setText(title);
    	textView.setTextColor(Color.WHITE);
    	textView.setGravity(Gravity.RIGHT);
    	textView.setPadding(TABLE_CELL_PADDING,TABLE_CELL_PADDING,TABLE_CELL_PADDING,TABLE_CELL_PADDING);
    	tableRow.addView(textView);
    	textView = new TextView(this);
    	textView.setText(text);
    	textView.setTextColor(Color.WHITE);
    	textView.setPadding(TABLE_CELL_PADDING,TABLE_CELL_PADDING,TABLE_CELL_PADDING,TABLE_CELL_PADDING);
    	tableRow.addView(textView);
    	if(title.contains("Phone")) {
    		Log.d(TAG,"Phone!"+text);
    		final String phoneNumber = "tel:"+text.trim();
//    		phoneNumber = "tel:8003738282";
    		ImageButton callButton = new ImageButton(this);
    		callButton.setBackgroundResource(R.drawable.call);
    		callButton.setOnClickListener(new OnClickListener() {
    			@Override
    			public void onClick(View v) {
    				Intent intent = new Intent(Intent.ACTION_CALL);
    				intent.setData(Uri.parse(phoneNumber));
    				startActivity(intent);
    			}
    		});
    		tableRow.addView(callButton);
    	}
    	tableLayout.addView(tableRow, new TableLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
    }
    
    /**
     * Adapted from a tutorial as http://www.vogella.de/articles/AndroidJSON/article.html
	 * It was for twitter, so grabbing twitter feeds should be just as easy
     * @param feed The link to use
     * @return A String of JSON Data
     */
    public String readCalendarFeed(String feed) {
    	StringBuilder builder = new StringBuilder();
    	HttpClient client=new DefaultHttpClient();
    	HttpGet httpGet = new HttpGet(feed);
    	try {
    		HttpResponse response = client.execute(httpGet);
    		StatusLine statusLine = response.getStatusLine();
    		int statusCode = statusLine.getStatusCode();
    		if(statusCode==200) { // Everything's all good.
    			HttpEntity entity = response.getEntity();
				InputStream content = entity.getContent();
				BufferedReader reader = new BufferedReader(
						new InputStreamReader(content));
				String line;
				while ((line = reader.readLine()) != null) {
					builder.append(line);
				}
    		} else { //Uh ooooh
    			Log.e(TAG,"Error getting feed:"+feed);
    		}    		
    	} catch (ClientProtocolException e) {
    		Log.e(TAG,"Client Protocol Exception="+e);
		} catch(IOException e) {
    		Log.e(TAG,"IO Exception="+e);
    	}
    	return builder.toString();
    }

	
	
	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.events);
        eventList = new ArrayList<CalendarEvent>();       
        //Setup Spinner
        Spinner spinner = (Spinner) findViewById(R.id.spinner);
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
                this, R.array.feed_array, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);
        spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());       

        try {
			// Do something
		} catch (Exception e) {
			reportException(e);
		}
        
    	reportLifeCycle("onCreate");
    }
    
    @Override
    protected void onStart() {

    	reportLifeCycle("onStart");
    	super.onStart();
    }

    @Override
    protected void onRestart() {

    	reportLifeCycle("onRestart");
    	super.onRestart();
    }
    
    @Override
    protected void onResume() {

    	reportLifeCycle("onResume");
    	super.onResume();
    }

    @Override
    protected void onPause() {
    	super.onPause();
    	reportLifeCycle("onPause");
    }
    
    @Override
    protected void onStop() {
    	super.onStop();
    	reportLifeCycle("onStop");
    }
   
    /** Called when the activity is finished. */
    @Override
    public void onDestroy() {
        super.onDestroy();

    	reportLifeCycle("onDestroy");
    }
    

    private void report(Object o) {

        Util.report(this, TAG, o, false);
	}
    
    private void reportLifeCycle(Object o) {

        Util.report(this, TAG, o+" completed successfully", false);
	}
    
    private void reportException(Object o) {

        Util.report(this, TAG, "Exception Thrown: "+o, true);

	}
    
	public void taskBarClick(View v) {
		if(v.getId() != R.id.goHomeButton)
			Util.taskBarClick(v);
	}
}